from PIL import Image
from pathlib import Path


def compress_image(source, dest, width):
    """
    将图片按指定宽度进行等比压缩并保存。
    如果原图宽度大于给定宽度，则缩放到该宽度；
    否则保持原尺寸，仅保存为 JPEG 并设置质量 80。

    参数
    ----------
    source : str | PathLike
        原始图片路径（可以是任何 PIL 支持的格式）。
    dest : str | PathLike
        输出图片路径（会被保存为 JPEG，因为 quality 参数只在 JPEG 时生效）。
    width : int
        目标宽度（像素）。

    注意
    ----------
    1. 未对 dest 的扩展名进行检查，如果 dest 为 png 等格式，quality 参数不会生效。
    2. resize 时 ys 为浮点数，PIL 要求整数尺寸，需强制转换。
    3. 未处理可能出现的 IOError / FileNotFoundError。
    4. 原图宽高比可能为 0（极端情况），需要保护。
    5. 没有关闭文件句柄，大文件或多次调用时可能泄露资源。
    """
    dest = Path(dest)
    # 如果父级目录不存在则创建
    dest.parent.mkdir(parents=True, exist_ok=True)
    # 打开原始图片
    with Image.open(source) as im:
        # 获取原始宽高
        x, y = im.size

        # 仅当原图宽度大于指定宽度时才缩放
        if x > width:
            xs = width
            ys = y / x * width  # ⚠️ 这里得到的是 float，需要 int()
            temp = im.resize((xs, int(ys)), Image.LANCZOS)  # 推荐指定采样方式
            temp.save(dest, quality=80)
        else:
            # 不缩放，直接保存
            im.save(dest, quality=80)
